//    Copyright (C) Kherty.  All rights reserved.
using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal class ColumnInfoRecord : WorksheetLevelRecord
    {
        internal const int MaxColumnIndex = 255;
        private bool _bestFit;
        private bool _fUserSet;
        private ushort _firstIndex;
        private bool _isCollapsed;
        private bool _isHidden;
        private ushort _lastIndex;
        private ushort _outlineLevel;
        private object _unused = (ushort) 0;
        private ushort _width;
        private ushort _xfid;

        public ColumnInfoRecord(Column first, Column last, BiffWriterWorkbookContext context)
        {
            Contract.Requires(first != null);
            Contract.Requires(last != null);
            Contract.Requires(first.OutlineLevel == last.OutlineLevel);
            Contract.Requires(first.Index <= MaxColumnIndex);
            Contract.Requires(last.Index <= MaxColumnIndex);
            _firstIndex = (ushort)first.Index;
            _lastIndex = (ushort) last.Index;
            if (first.FormattingRecord != null)
            _xfid = context.CellStyleRecordTable[first.FormattingRecord];
            _isHidden = first.IsHidden;
            _width = (ushort) (256*first.CharacterWidth.GetValueOrDefault(8)); //\\ sure?
            this._outlineLevel = (ushort) first.OutlineLevel;
            this._isCollapsed = first.IsCollapsed;
        }

        public ColumnInfoRecord()
        {
        }

        internal override BiffRecordType RecordType
        {
            get { return BiffRecordType.ColInfo; }
        }

        protected ushort Flags
        {
            get
            {
                ushort result = 0;
                if (_isHidden)
                    result |= 0x1;
                if (_fUserSet)
                    result |= 0x2;
                if (_bestFit)
                    result |= 0x4;
                result |= (ushort) (_outlineLevel << 8);
                if (_isCollapsed)
                    result |= 0x1000;
                return result;
            }
        }

        internal override void WriteContent(BiffWriterWorkbookContext context)
        {
            context.Writer.Write(_firstIndex);
            context.Writer.Write(_lastIndex);
            context.Writer.Write(_width);
            context.Writer.Write(_xfid);
            context.Writer.Write(Flags);
            if (_unused is byte)
                context.Writer.Write((byte) _unused);
            else
            {
                context.Writer.Write((ushort) _unused);
            }
        }

        protected override void ReadContent(BiffReaderContext context, int length)
        {
            Contract.Assert(length == 12 || length == 11);
            _firstIndex = context.ReadUInt16();
            _lastIndex = context.ReadUInt16();
            _width = context.ReadUInt16();
            _xfid = context.ReadUInt16();
            ushort flags = context.ReadUInt16();
            _isHidden = (flags & 0x1) != 0;
            _fUserSet = (flags & 0x02) != 0;
            _bestFit = (flags & 0x04) != 0;
            _outlineLevel = (ushort) ((flags & 0x0700) >> 8);
            _isCollapsed = (flags & 0x1000) != 0;
            Contract.Assert(flags == Flags);
            if (length == 12)
                _unused = context.ReadUInt16();
            else
            {
                _unused = context.ReadByte();
            }
        }

        internal override void Apply(BiffReaderWorksheetContext context)
        {
            var formattingRecord = context.WorkbookContext.GetCellFormattingRecord(_xfid);
            for (int colIndex = _firstIndex; colIndex <= _lastIndex; colIndex++)
            {
                Column c = context.Worksheet.Columns[colIndex];
                c.CharacterWidth = ((double) _width)/256;
                c.IsVisible = !_isHidden;
                c.SetFormattingRecord(formattingRecord);
                //\\iscollapsed, outlinelevel
            }
            context.ColumnGroupStack.ApplyOutlineLevel(context.Worksheet.Columns[_firstIndex],
                context.Worksheet.Columns[_lastIndex], (byte)this._outlineLevel, !this._isHidden, this._isCollapsed);

        }
    }
}